home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Nebula 1
/
Nebula One.iso
/
Utilities
/
Workspace
/
LibInspector
/
Source
/
LibInspector.m
< prev
next >
Wrap
Text File
|
1995-06-12
|
9KB
|
311 lines
//----------------------------------------------------------------------------------------------------
//
// LibInspector
//
// Inherits From: WMInspector
//
// Declared In: LibInspector.h
//
// Disclaimer
//
// You may freely copy, distribute and reuse this software and its
// associated documentation. I disclaim any warranty of any kind,
// expressed or implied, as to its fitness for any particular use.
//
//----------------------------------------------------------------------------------------------------
#import "LibInspector.h"
#define AR_TV "ar tv"
#define AR_X "ar x"
#define CD "cd"
#define MKDIR "mkdir"
#define EXTRACTION_FOLDER "/tmp/LibExtractions"
#define OUT_OF_MEMORY "Out of Memory!"
#define MKDIR_ERROR "Unable to create temporary folder!"
#define PROCESS_ERROR "Unable to open process stream!"
#define PARSE_ERROR "Unable to recognize library information!"
#define MAX_AR_FILENAME_LEN 16
static FILE* responseStream;
@implementation LibInspector
static id _SELF = nil;
//----------------------------------------------------------------------------------------------------
// Private Methods
//----------------------------------------------------------------------------------------------------
- _alert: (STR) errorMessage
{
NXRunAlertPanel (NULL, "%s", NULL, NULL, NULL, errorMessage);
return self;
}
- _getTableOfContents
{
// Get library's table of contents by sending AR_TV command.
// Response stream will be read to populate browser (in brower:fillMatrix:inColumn).
STR command;
char currentPath [MAXPATHLEN+1];
[self selectionPathsInto:currentPath separator:'\0'];
if (! (command = malloc (strlen (AR_TV) + strlen (currentPath) + 2)))
{
[self _alert: OUT_OF_MEMORY];
return nil;
}
sprintf (command, "%s %s", AR_TV, currentPath);
if (! (responseStream = popen (command, "r")))
{
if (command) free (command);
[self _alert: PROCESS_ERROR];
return nil;
}
if (command) free (command);
return self;
}
- (BOOL)_createLibExtractionFolder
{
// Make a temporary directory for extractions (EXTRACTION_FOLDER).
// Return YES if exists/successful, NO if error.
STR command;
struct stat statBuffer;
if (stat (EXTRACTION_FOLDER, &statBuffer) == 0) return YES;
if (! (command = malloc (strlen (MKDIR) + strlen (EXTRACTION_FOLDER) + 2)))
{
[self _alert: OUT_OF_MEMORY];
return NO;
}
sprintf (command, "%s %s", MKDIR, EXTRACTION_FOLDER);
system (command);
if (stat (EXTRACTION_FOLDER, &statBuffer) != 0)
{
if (command) free (command);
[self _alert: MKDIR_ERROR];
return NO;
}
if (command) free (command);
return YES;
}
- _openLibExtractionsFileViewer
{
// Search the application's windowList for the LibExtractions FileViewer.
// Open the window if it exists, open a new one if not. This will prevent
// multiple FileViewers from being displayed.
int iterator;
int openStatus;
id windowList = [NXApp windowList];
id libExtractionsFileViewer = nil;
id appListener = NXResponsibleDelegate ([NXApp appListener], @selector(openFile:ok:));
for (iterator = 0; iterator < [windowList count]; iterator++)
if (NXOrderStrings ([[windowList objectAt:iterator] title], "LibExtractions",
YES, strlen ("LibExtractions"), NULL) == 0)
libExtractionsFileViewer = [windowList objectAt:iterator];
if (libExtractionsFileViewer)
if ([libExtractionsFileViewer style] == NX_MINIWINDOWSTYLE)
[libExtractionsFileViewer deminiaturize:nil];
else
[libExtractionsFileViewer makeKeyAndOrderFront:nil];
else
[appListener openFile: EXTRACTION_FOLDER ok: &openStatus];
return self;
}
- _extractSelectedFiles
{
// Extract selected files into a temporary folder and open that folder.
id selectionList = [browser getSelectedCells: nil];
int iterator;
STR command;
STR filename;
char currentPath [MAXPATHLEN+1];
if ([selectionList count]) if (! [self _createLibExtractionFolder]) return nil;
[self selectionPathsInto: currentPath separator:'\0'];
if (! (command = malloc (strlen (CD) + strlen (EXTRACTION_FOLDER) +
strlen (AR_X) + MAXPATHLEN + MAX_AR_FILENAME_LEN + 10)))
{
[self _alert: OUT_OF_MEMORY];
return nil;
}
for (iterator = 0; iterator < [selectionList count]; iterator++)
{
filename = NXCopyStringBuffer ([[selectionList objectAt: iterator] stringValue]);
if (! (filename = strtok (filename, " \t\n")))
{
if (command) free (command);
return nil;
}
sprintf (command, "%s %s; %s %s %s", CD, EXTRACTION_FOLDER, AR_X,
currentPath, filename);
system (command);
if (filename) free (filename);
}
[self _openLibExtractionsFileViewer];
if (command) free (command);
return self;
}
- (STR)_format: (STR)responseLine
{
// Parse and format the response line. Where a token gets memcpy'd within the
// formatString indicates its position within the displayed string. Have to exclude
// some information. Also, throw out names beginning with '__.'. These are archive
// table names, header stuff, etc., (or possibly very weird file names). Returns a
// formatted string that the caller must free, or some error condition.
// (example response line) "rw-r--r-- 0/1 4572 Jul 29 23:53 1992 NXImage.o".
STR currentToken;
char formatString[51];
memset (formatString, ' ', 50);
formatString [50] = '\0';
if (! strtok (responseLine, " \t")) return PARSE_ERROR;
if (! strtok (NULL, " \t")) return PARSE_ERROR;
if (! (currentToken = strtok (NULL, " \t\n"))) return PARSE_ERROR;
memcpy (formatString + 18, currentToken, strlen (currentToken));
if (! (currentToken = strtok (NULL, " \t\n"))) return PARSE_ERROR;
memcpy (formatString + 26, currentToken, strlen (currentToken));
if (! (currentToken = strtok (NULL, " \t\n"))) return PARSE_ERROR;
memcpy (formatString + 30, currentToken, strlen (currentToken));
if (! (currentToken = strtok (NULL, " \t\n"))) return PARSE_ERROR;
if (! (currentToken = strtok (NULL, " \t\n"))) return PARSE_ERROR;
memcpy (formatString + 33, currentToken, strlen (currentToken));
if (! (currentToken = strtok (NULL, " \t\n"))) return PARSE_ERROR;
memcpy (formatString, currentToken, strlen (currentToken));
if (NXOrderStrings (currentToken, "__.", NO, 3, NULL) == 0) return NULL;
return NXCopyStringBuffer (formatString);
}
//----------------------------------------------------------------------------------------------------
// WMInspector Methods
//----------------------------------------------------------------------------------------------------
+ new
{
// Required/called by WM. Only allow one instance...
char path[MAXPATHLEN+1];
id bundle;
if (_SELF) return _SELF;
_SELF = self = [super new];
if ( ! (bundle = [NXBundle bundleForClass:[LibInspector class]] ) ) return nil;
if ( ! [bundle getPath:path forResource:"LibInspector" ofType:"nib"] ) return nil;
[NXApp loadNibFile:path owner:self withNames:NO fromZone:[self zone]];
return _SELF;
}
- revert: sender
{
// Called by WM when file selection is type we inspect.
[self _getTableOfContents];
[[[self okButton] setTitle: "Extract"] setIconPosition: NX_TITLEONLY];
[browser loadColumnZero];
return [super revert: sender];
}
- ok:sender
{
// User pressed 'Extract' button...
[self _extractSelectedFiles];
return [super ok:sender];
}
//----------------------------------------------------------------------------------------------------
// Action Methods
//----------------------------------------------------------------------------------------------------
- browserClicked: sender
{
// A file or files have been selected in the browser. Enable 'Extract'
// button if not an empty selection.
if ([browser selectedCell])
[[self okButton] setEnabled: YES];
else
[[self okButton] setEnabled: NO];
return self;
}
//----------------------------------------------------------------------------------------------------
// Browser Delegate Method
//----------------------------------------------------------------------------------------------------
- (int) browser: aBrowser fillMatrix: aMatrix inColumn: (int)aColumn
{
// Populate Table Of Contents browser with formatted command response.
// Set the font for the browser text here (fixed font for even column alignment).
// Minimal error checking within read loop - NULL indicates an entry we want
// to skip (like an archive header), PARSE_ERROR indicates a response that
// could not be recognized, all else are considered successful.
id font = [Font newFont: "Courier" size: 10];
int count = 0;
char nextLine [81];
STR formattedLine;
while (fgets (nextLine, 999, responseStream))
{
if ( (formattedLine = [self _format: nextLine]) == NULL) continue;
if ( NXOrderStrings (formattedLine, PARSE_ERROR, YES, -1, NULL) == 0)
{
[self _alert: PARSE_ERROR];
break;
}
[aMatrix renewRows: (count+1) cols: 1];
[[aMatrix cellAt: count :0] setFont: font];
[[aMatrix cellAt: count :0] setStringValue: formattedLine];
[[[aMatrix cellAt: count :0] setLoaded: YES] setLeaf: YES];
if (formattedLine) free (formattedLine);
count++;
}
if (font) [font free];
pclose (responseStream);
return count;
}
@end